<?

/*
	Document manager auth_pop3.php module

	WARNING: this modules uses e-mail address to check
	login and password against pop3 server! e-mail must be
	in following form:

	login_on_pop3_server@pop3_server.domain

	That should actually be also a vaild e-mail address


	this module is based on class.POP3.php3 by cdi@thewebmasters.net
*/

function auth_pop3($user) {
	$email = explode("@",$user[3]);
	$pop3 = new POP3();
	$pop3->connect($email[1]);
	if ($pop3->checklogin($email[0],$GLOBALS[PHP_AUTH_PW])) {
		$pop3->quit();
		return true;
	}
	$pop3->quit();
	return false;
}

//--------------------------------------------------------------------------

/*
	This is just a part of class.POP3.php3 which is needed for
	auth_pop3.php module. Please look at original location for
	whole class!

	class.POP3.php3 v1.0	99/03/24 CDI cdi@thewebmasters.net
	Copyright (c) 1999 - CDI (cdi@thewebmasters.net) All Rights Reserved

	An RFC 1939 compliant wrapper class for the POP3 protocol.
*/

class POP3
{
	var $ERROR	= "";	// Error string.

	var $TIMEOUT	= 60;	// Default timeout before giving up on a
				// network operation.

	var $COUNT	= -1;	// Mailbox msg count

	var $BUFFER	= 512;	// Socket buffer for socket fgets() calls.
				// Per RFC 1939 the returned line a POP3
				// server can send is 512 bytes.

	var $FP		= "";	// The connection to the server's
				// file descriptor

	var $MAILSERVER	= "";	// Set this to hard code the server name

	var $DEBUG	= false;// set to true to echo pop3
				// commands and responses to error_log
				// this WILL log passwords!

	var $BANNER	= "";	// Holds the banner returned by the
				// pop server - used for apop()

	function POP3 ( $server = "", $timeout = "" )
	{
		settype($this->BUFFER,"integer");
		if(!empty($server))
		{
			// Do not allow programs to alter MAILSERVER
			// if it is already specified. They can get around
			// this if they -really- want to, so don't count on it.
			if(empty($this->MAILSERVER))
			{
				$this->MAILSERVER = $server;
			}
		}
		if(!empty($timeout))
		{
			settype($timeout,"integer");
			$this->TIMEOUT = $timeout;
			set_time_limit($timeout);
		}
		return true;
	}

	function update_timer ()
	{
		set_time_limit($this->TIMEOUT);
		return true;
	}

	function connect ($server, $port = 110)
	{
		// Opens a socket to the specified server. Unless overridden,
		// port defaults to 110. Returns true on success, false on fail

		// If MAILSERVER is set, override $server with it's value

		if(!empty($this->MAILSERVER))
		{
			$server = $this->MAILSERVER;
		}

		if(empty($server))
		{
			$this->ERROR = "POP3 connect: No server specified";  
			unset($this->FP);
			return false;
		}

		$fp = fsockopen("$server", $port, &$errno, &$errstr);

		if(!$fp)
		{
			$this->ERROR = "POP3 connect: Error [$errno] [$errstr]";
			unset($this->FP);
			return false;
		}

		set_socket_blocking($fp,-1);
		$this->update_timer();
		$reply = fgets($fp,$this->BUFFER);
		$reply = $this->strip_clf($reply);
		if($this->DEBUG) { error_log("POP3 SEND [connect: $server] GOT [$reply]",0); }
		if(!$this->is_ok($reply))
		{
			$this->ERROR = "POP3 connect: Error [$reply]";
			unset($this->FP);
			return false;
		}
		$this->FP = $fp;
		$this->BANNER = $this->parse_banner($reply);
		return true;
	}

//-----------------------------

	function checklogin ($user, $pass) {
		$reply = $this->send_cmd("USER $user");
		if(!$this->is_ok($reply))
		{
			$this->ERROR = "POP3 user: Error [$reply]";
			return false;
		}

		$reply = $this->send_cmd("PASS $pass");
		if(!$this->is_ok($reply))
		{
			$this->ERROR = "POP3 pass: authentication failed [$reply]";
			$this->quit();
			return false;
		}
		//	Auth successful.
		return true;
	}

//-------------------------------------------

	function noop ()
	{
		if(!isset($this->FP))
		{
			$this->ERROR = "POP3 noop: No connection to server";
			return false;
		}
		$cmd = "NOOP";
		$reply = $this->send_cmd($cmd);
		if(!$this->is_ok($reply))
		{
			return false;
		}
		return true;
	}

	function send_cmd ( $cmd = "" )
	{
		//	Sends a user defined command string to the
		//	POP server and returns the results. Useful for
		//	non-compliant or custom POP servers.
		//	Do NOT include the \r\n as part of your command
		//	string - it will be appended automatically.

		//	The return value is a standard fgets() call, which
		//	will read up to $this->BUFFER bytes of data, until it
		//	encounters a new line, or EOF, whichever happens first.

		//	This method works best if $cmd responds with only
		//	one line of data.

		if(!isset($this->FP))
		{
			$this->ERROR = "POP3 send_cmd: No connection to server";
			return false;
		}

		if(empty($cmd))
		{
			$this->ERROR = "POP3 send_cmd: Empty command string";
			return "";
		}

		$fp = $this->FP;
		$buffer = $this->BUFFER;
		$this->update_timer();
		fwrite($fp,"$cmd\r\n");
		$reply = fgets($fp,$buffer);
		$reply = $this->strip_clf($reply);
		if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
		return $reply;
	}

	function quit ()
	{
		//	Closes the connection to the POP3 server, deleting
		//	any msgs marked as deleted.

		if(!isset($this->FP))
		{
			$this->ERROR = "POP3 quit: connection does not exist";
			return false;
		}
		$fp = $this->FP;
		$cmd = "QUIT";
		fwrite($fp,"$cmd\r\n");
		$reply = fgets($fp,$this->BUFFER);
		$reply = $this->strip_clf($reply);
		if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
		fclose($fp);
		unset($this->FP);
		return true;
	}

	//	*********************************************************

	//	The following methods are internal to the class.

	function is_ok ($cmd = "")
	{
		//	Return true or false on +OK or -ERR

		if(empty($cmd))	{ return false; }
		if ( ereg ("^\+OK", $cmd ) )	{ return true; }
		return false;
	}

	function strip_clf ($text = "")
	{
		// Strips \r\n from server responses

		if(empty($text)) { return $text; }
		$stripped = ereg_replace("\r","",$text);
		$stripped = ereg_replace("\n","",$stripped);
		return $stripped;
	}

	function parse_banner ( $server_text )
	{
		$outside = true;
		$banner = "";
		$length = strlen($server_text);
		for($count =0; $count < $length; $count++)
		{
			$digit = substr($server_text,$count,1);
			if(!empty($digit))
			{
				if( (!$outside) and ($digit != '<') and ($digit != '>') )
				{
					$banner .= $digit;
				}
				if ($digit == '<')
				{
					$outside = false;
				}
				if($digit == '>')
				{
					$outside = true;
				}
			}
		}
		$banner = $this->strip_clf($banner);	// Just in case
		return "<$banner>";
	}

}	// End class

?>
